#include <QFileDialog>
#include <QMessageBox>
#include <QSqlTableModel>
#include <QSqlRecord>
#include <QSqlError>
#include <QDebug>
#include "registerinterface.h"
#include "ui_registerinterface.h"
#include "FaceObject/faceobject.h"

RegisterInterface::RegisterInterface(QWidget *parent)
    : QWidget(parent), ui(new Ui::RegisterInterface) {
    ui->setupUi(this);
}

RegisterInterface::~RegisterInterface() {
    delete ui;
    cap_.release();  // 确保释放摄像头资源
}

void RegisterInterface::timerEvent(QTimerEvent *e) {
    // 获取摄像头数据并显示在界面上
    cap_ >> frame_;
    if (frame_.empty()) {
        return;
    }
    // 确保图像数据连续
    if (!frame_.isContinuous()) {
        frame_ = frame_.clone();
    }
    // 将opencv中的Mat数据（BGR格式）转成QImage数据（RGB格式）
    cv::cvtColor(frame_, frame_, cv::COLOR_BGR2RGB);
    QImage img(frame_.data, frame_.cols, frame_.rows, frame_.step, QImage::Format_RGB888);  // 创建图像
    // 通过放大和裁剪图像使其尺寸与对应的标签控件相匹配（使用平滑插值算法以减少缩放后的图像失真和锯齿现象）
    img = img.scaled(ui->face_image->size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
    int ow = img.width();
    int oh = img.height();
    int sx = (ow - 450) / 2;
    int sy = (oh - 470) / 2;
    img = img.copy(sx, sy, 450, 470);
    // 生成并显示图像
    ui->face_image->setPixmap(QPixmap::fromImage(img));
}

void RegisterInterface::on_reset_btn_clicked() {
    // 清空输入栏数据
    ui->name_inp->clear();
    ui->birthday_inp->setDate(QDate(2000, 1, 1));
    ui->addr_inp->clear();
    ui->img_path_inp->clear();
    ui->phone_inp->clear();
    ui->depa_inp->clear();
    ui->face_image->clear();
}

void RegisterInterface::on_select_head_btn_clicked() {
    // 通过文件对话框选中图片路径并添加到输入框
    // 先打开一个文件选择对话框，返回选中的文件路径，参数为对话框的父窗口（即当前窗口）
    QString path = QFileDialog::getOpenFileName(this);
    ui->img_path_inp->setText(path);
    // 显示图片
    QPixmap pmp(path);
    if (pmp.isNull()) {  // 未成功打开任何图片，直接返回
        return;
    }
    pmp = pmp.scaledToWidth(ui->face_image->width());  // 缩放图像，高度自适应
    ui->face_image->setPixmap(pmp);
}

void RegisterInterface::on_register_btn_clicked() {
    // 注册功能实现
    /* 注意：由于人脸数据写入到磁盘有延迟（一般在客户端关闭后写入），因此当场注册的人脸并不会立即在客户端生效（需要重启一下） */
    // 1.通过照片结合FaceObject模块获取faceID
    if (ui->name_inp->text().isEmpty()) {
        QMessageBox::information(this, "注册提示", "请填写姓名！");
        return;
    }
    if (ui->depa_inp->text().isEmpty()) {
        QMessageBox::information(this, "注册提示", "请填写部门！");
        return;
    }
    if (ui->img_path_inp->text().isEmpty()) {
        QMessageBox::information(this, "注册提示", "请选择/拍摄头像图片！");
        return;
    }
    frame_ = cv::imread(ui->img_path_inp->text().toUtf8().data());  // 读取人脸图像文件
    // 检测图片中是否存在人脸
    if (!FaceObject::getInstance()->detectFace(frame_)) {
        QMessageBox::information(this, "注册提示", "未检测到人脸信息，请重新选择头像！");
        return;
    }
    // 注册人脸并得到id（faceRegister的实现会自动将face_id保存到人脸数据库）
    auto face_id = FaceObject::getInstance()->faceRegister(frame_);
    if (face_id < 0) {
        qDebug() << "RegisterInterface::on_register_btn_clicked(): 人脸注册失败！\n";
        QMessageBox::information(this, "注册提示", "注册失败！");
        return;
    }
    // 将头像图片保存到一个固定路径下，文件名直接为本人姓名
    QDir cur;
    QString save_path = QString("%1/faceimg/%2.jpg")
                            .arg(cur.absolutePath())
                            .arg(static_cast<QString>(ui->name_inp->text().toUtf8().toBase64()));
    cv::imwrite(save_path.toUtf8().data(), frame_);
    // 2.将个人信息存储到数据表staff_info中
    QSqlTableModel tbl_model;                // 用于操作数据库表的模型类
    tbl_model.setTable("staff_info");        // 与数据库中的对应表绑定
    QSqlRecord record = tbl_model.record();  // 创建一条新的对应表的空记录
    // 填写记录中的字段数据
    record.setValue("staff_name", ui->name_inp->text());
    record.setValue("staff_sex", ui->man_opt->isChecked() ? 1 : 0);
    record.setValue("staff_birth", ui->birthday_inp->text());
    record.setValue("staff_phone", ui->phone_inp->text());
    record.setValue("staff_depa", ui->depa_inp->text());
    record.setValue("staff_addr", ui->addr_inp->text());
    record.setValue("staff_face_id", face_id);
    record.setValue("staff_img_file_path", save_path);  // 头像路径
    // 3.未发生错误时，提示注册成功
    if (!tbl_model.insertRecord(0, record) || !tbl_model.submitAll()) {
        qDebug() << "Database insert failed:" << tbl_model.lastError().text();
        QMessageBox::information(this, "注册提示", "注册失败！");
        return;
    }
    QMessageBox::information(this, "注册提示", "注册成功！");
}

void RegisterInterface::on_open_cap_btn_clicked() {
    // 设置按钮文本
    if (ui->open_cap_btn->text() == "开启摄像头") {
        ui->open_cap_btn->setText("关闭摄像头");
        cap_.open(0);                 // 打开摄像头
        timer_id_ = startTimer(100);  // 开启定时器事件
    } else {
        cap_.release();               // 关闭摄像头
        killTimer(timer_id_);         // 关闭定时器事件
        ui->open_cap_btn->setText("开启摄像头");
        ui->face_image->clear();
    }
}

void RegisterInterface::on_shoot_btn_clicked() {
    if (!cap_.isOpened()) {
        qDebug() << "RegisterInterface::on_shoot_btn_clicked(): 摄像头未开启！\n";
        return;
    }
    // 保存img捕捉到的数据
    QString save_path = QString(QDir().absolutePath() + "/takephotos/ph%1.jpg").arg(rand());
    ui->img_path_inp->setText(save_path);
    cv::cvtColor(frame_, frame_, cv::COLOR_BGR2RGB);
    cv::imwrite(save_path.toUtf8().data(), frame_);
    killTimer(timer_id_);  // 关闭定时器事件
    cap_.release();        // 关闭摄像头
    ui->open_cap_btn->setText("开启摄像头");
}
